//package strategy;
//
//import algorithm.Greenwave;
//import algorithm.Kdalgorithm;
//import com.openatc.core.common.IErrorEnumImplOuter;
//import com.openatc.core.model.RESTRetBase;
//import com.openatc.core.util.RESTRetUtils;
//import com.openatc.model.model.Feature;
//import com.openatc.model.model.Pattern;
//import com.openatc.model.model.Phase;
//import com.openatc.model.model.Split;
//import com.openatc.optimize.fixedtimeplan.config.cross.CrossConfig;
//import com.openatc.optimize.fixedtimeplan.config.cross.Ring;
//import com.openatc.optimize.fixedtimeplan.model.control.Cross;
//import com.openatc.optimize.fixedtimeplan.model.control.FixedtimePlan;
//import model.RouteIntsection;
//import model.RouteOpt;
//import model.RoutePara;
//import org.springframework.util.CollectionUtils;
//
//import java.util.*;
//import java.util.logging.Logger;
//import java.util.stream.Collectors;
//
///**
// * @Classname RouteOptStrategy
// * @Description
// * @Date 2022/5/29 17:44
// * @Created by panleilei
// */
//public class RouteOptStrategy {
//
//    private Kdalgorithm kdalgorithm = new Kdalgorithm();
//
//    private Logger logger = Logger.getLogger(RouteOptStrategy.class.getSimpleName());
//
//    /**
//     * 红波协调
//     * @param routePara
//     * @return
//     */
//    public RESTRetBase getRedRouteOpt(RoutePara routePara) {
//        List<RouteIntsection> devs = routePara.getDevs();
//        // 没有协调路口
//        if (CollectionUtils.isEmpty(devs)){
//            return RESTRetUtils.errorObj(IErrorEnumImplOuter.E_5003);
//        }
//
//        RouteOpt routeOpt = new RouteOpt();
//        routeOpt.setDevs(devs);
//
//        String type = routePara.getDirection(); // 上行/下行
//        // devs转成map，sortid为key
//        Map<Integer, RouteIntsection> devsMap = devs.stream().collect(Collectors.toMap(RouteIntsection::getSortid, dev -> dev));
//
//        try {
//            int offsets[] = new int[routePara.getDevs().size()]; // 保存优化后的相位差
//            int intssplit[] = new int[routePara.getDevs().size()]; // 保存路口协调相位绿信比的值
////            int intsdistances[] = new int[routePara.getDevs().size()]; // 保存各路口的距离
//            // 获取关键路口的周期
//            int keyCycle = calKeyIntersectionCycle(routePara.getKeyintsid(),devs);
//            // 初始化各路口协调相位绿信比
//            for (RouteIntsection dev : devs) {
//                // 优化各路口周期
//                cycleopt(keyCycle,dev.getFeature());
//                // 保存各路口相位差
//                offsets[dev.getSortid() - 1] = dev.getFeature().getPatternList().get(0).getOffset();
//                // 保存各路口距离
////                intsdistances[dev.getSortid() - 1] = dev.getDistance();
//                // 协调相位号
//                int phaseno;
//                if (type.equals("up")) {
//                    phaseno = dev.getForwardphaseid();
//                } else {
//                    phaseno = dev.getBackphaseid();
//                }
//
//                List<List<Split>> rings = dev.getFeature().getPatternList().get(0).getRings();
//                // 获取参与协调相位的绿信比
//                label:
//                for (int i = 0; i < rings.size(); i++) {
//                    for (Split split : rings.get(i)) {
//                        if (phaseno == split.getId()) {
//                            intssplit[dev.getSortid() - 1] = split.getValue();
//                            break label;
//                        }
//                    }
//                }
//            }
//            List<RouteIntsection> routeOptList = routeOpt.getDevs();
//
//            // 协调速度
//            double speed = calCoordinationSpeed(routePara);
//            // 计算每个路口的相位差
//            // 上行
//            if (type.equals("up")) {
//                for (RouteIntsection dev : routeOptList) {
//                    if (dev.getSortid() == 1) {
//                        continue;
//                    }
//                    int distance = dev.getDistance() + devsMap.get(dev.getSortid() - 1).getWidth();
//                    offsets = kdalgorithm.redwaveOffsetOptUp(distance, speed, intssplit, keyCycle, dev.getSortid(), offsets);
//                }
//            }
//            // 下行
//            else {
//                Collections.reverse(routeOptList);
//                for (RouteIntsection dev : routeOptList) {
//                    if (dev.getSortid() == routeOptList.size()) {
//                        continue;
//                    }
//                    int sortid = dev.getSortid();
//                    int distance = devsMap.get(sortid + 1).getDistance() + devsMap.get(sortid + 1).getWidth();
//                    offsets = kdalgorithm.redwaveOffsetOptDown(speed, intssplit, keyCycle, dev.getSortid(), offsets, distance);
//                }
//                Collections.reverse(routeOptList);
//            }
//
//            for (RouteIntsection dev : routeOptList) {
//                // 改变路口相位差
//                dev.getFeature().getPatternList().get(0).setOffset(offsets[dev.getSortid() - 1]);
//            }
//            // 获取Wave
//            Greenwave greenwave;
//            int width = kdalgorithm.getMotorcadeWidth(intssplit);
//            if (routePara.getDirection().equals("up")) {
//                greenwave = kdalgorithm.getMUp(type, speed, width);
//            } else {
//                greenwave = kdalgorithm.getMDown(type, speed, width);
//            }
//            List<Greenwave> greenwaves = new LinkedList<>();
//
//            greenwaves.add(greenwave);
//
//            routeOpt.setGreenwave(greenwaves);
//            return RESTRetUtils.successObj(routeOpt);
//        } catch (Exception e){
//            logger.info(e.getMessage());
//            return RESTRetUtils.errorObj(IErrorEnumImplOuter.E_5003);
//        }
//    }
//
//    /**
//     * 计算关键路口的周期
//     * @param keyintsid
//     * @param devs
//     * @return
//     */
//    private int calKeyIntersectionCycle(String keyintsid, List<RouteIntsection> devs) {
//       return devs.stream().filter(
//                dev -> keyintsid.equals(dev.getAgentid())).findFirst().get().getFeature().getPatternList().get(0).getCycle();
//    }
//
//    /**
//     * 计算协调速度
//     * @param routePara
//     * @return
//     */
//    private double calCoordinationSpeed(RoutePara routePara) {
//        // 协调方向
//        String type = routePara.getDirection();
//        // 上行
//        if ("up".equals(type)){
//            return routePara.getUpspeed();
//        }
//        // 下行
//        else {
//            return routePara.getDownspeed();
//        }
//    }
//
//    /**
//     * 判断周期长度是否一致
//     * @param intscycle
//     * @return
//     */
//    private boolean isAllCycleEqual(int[] intscycle) {
//        if (intscycle.length == 0){
//            return false;
//        }
//        int firstElement = intscycle[0];
//        for (int i : intscycle){
//            if (firstElement != i){
//                return false;
//            }
//        }
//        return true;
//    }
//
//    /**
//     * 车队尾协调策略
//     * @param routePara
//     * @return
//     */
//    public RESTRetBase getLastOfMotorcadeRouteOpt(RoutePara routePara) {
//        List<RouteIntsection> devs = routePara.getDevs();
//        if (CollectionUtils.isEmpty(devs)) {
//            return RESTRetUtils.errorObj(IErrorEnumImplOuter.E_5003);
//        }
//
//        RouteOpt routeOpt = new RouteOpt();
//        routeOpt.setDevs(routePara.getDevs());
//
//        try {
//            int offsets[] = new int[routePara.getDevs().size()]; // 保存优化后的相位差
//            int intssplit[] = new int[routePara.getDevs().size()]; // 保存路口协调相位绿信比的值
//            int intsdistances[] = new int[routePara.getDevs().size()]; // 保存各路口的距离
//            int keyCycle = calKeyIntersectionCycle(routePara.getKeyintsid(), devs);
//            // 初始化各路口协调相位绿信比
//            for (RouteIntsection dev : devs) {
//                cycleopt(keyCycle,dev.getFeature());
//                // 保存周期
//                offsets[dev.getSortid() - 1] = dev.getFeature().getPatternList().get(0).getOffset();
//                // 保存各路口距离
//                intsdistances[dev.getSortid() - 1] = dev.getDistance();
//                // 协调相位号
//                int phaseno;
//                if (routePara.getDirection().equals("up")) {
//                    phaseno = dev.getForwardphaseid();
//                } else {
//                    phaseno = dev.getBackphaseid();
//                }
//
//                List<List<Split>> rings = dev.getFeature().getPatternList().get(0).getRings();
//                // 获取参与协调相位的绿信比
//                label:
//                for (int i = 0; i < rings.size(); i++) {
//                    for (Split split : rings.get(i)) {
//                        if (phaseno == split.getId()) {
//                            intssplit[dev.getSortid() - 1] = split.getValue();
//                            break label;
//                        }
//                    }
//                }
//            }
//
//            List<RouteIntsection> routeOptList = routeOpt.getDevs();
//
//            // 协调速度
//            double speed = calCoordinationSpeed(routePara);
//            // 计算每个路口的相位差
//            // 上行
//            if (routePara.getDirection().equals("up")) {
//                for (RouteIntsection dev : routeOptList) {
//                    int distance = dev.getDistance();
//                    offsets = kdalgorithm.motorcadeOffsetOptUp(distance, speed, intssplit, keyCycle, dev.getSortid(), offsets);
//                }
//            }
//            // 下行
//            else {
//                Collections.reverse(routeOptList);
//                for (RouteIntsection dev : routeOptList) {
//                    offsets = kdalgorithm.motorcadeOffsetOptDown(speed, intssplit, keyCycle, dev.getSortid(), offsets, intsdistances);
//                }
//                Collections.reverse(routeOptList);
//            }
//
//            for (RouteIntsection dev : routeOptList) {
//                // 改变路口相位差
//                dev.getFeature().getPatternList().get(0).setOffset(offsets[dev.getSortid() - 1]);
//            }
//            // 获取Wave
//            String type = routePara.getDirection(); // 上行/下行
//            Greenwave greenwave;
//            int width = kdalgorithm.getMotorcadeWidth(intssplit);
//            if (routePara.getDirection().equals("up")) {
//                greenwave = kdalgorithm.getMUp(type, speed, width);
//            } else {
//                greenwave = kdalgorithm.getMDown(type, speed, width);
//            }
//            List<Greenwave> greenwaves = new LinkedList<>();
//            greenwaves.add(greenwave);
//
//            routeOpt.setGreenwave(greenwaves);
//            return RESTRetUtils.successObj(routeOpt);
//        } catch (Exception e){
//            logger.info(e.toString());
//            return RESTRetUtils.errorObj(IErrorEnumImplOuter.E_5003);
//        }
//    }
//
//    /**
//     * 绿波协调
//     * @param routePara
//     * @return
//     */
//    public RESTRetBase getGreenRouteOpt(RoutePara routePara) {
//
//        //计算优化
//        double intslenth[] = new double[routePara.getDevs().size()]; //保存路口长度的值
//        double intslenthup[] = new double[routePara.getDevs().size()]; //保存上行路口长度的值
//        double intslenthdown[] = new double[routePara.getDevs().size()]; //保存下行路口长度的值
//
//        int intssplit[] = new int[routePara.getDevs().size()]; //保存路口协调相位绿信比的值
//
//        int intsoffset[] = new int[routePara.getDevs().size()]; //保存优化后各路口的相位差的值
//        int intsabs[] = new int[routePara.getDevs().size()];//各路口协调相位所属周期时间位置，用来计算绝对相位差
//        int intscycle[] = new int[routePara.getDevs().size()];  // 保存各路口周期长度
//
//        try {
//            double intsvelup = 0.00;
//            double intsveldown = 0.00;
//
//            intsvelup = routePara.getUpspeed();
//            intsveldown = routePara.getDownspeed();
//
//            List<RouteIntsection> deviceList = routePara.getDevs();
//
//            String keyAgentid = routePara.getKeyintsid();
//            int keyCycle = 0;
//            // 得到关键路口的周期
//            for (RouteIntsection device : deviceList) {
//                if( keyAgentid.equals( device.getAgentid() ) ){
//                    keyCycle = device.getFeature().getPatternList().get(0).getCycle();
//                    break;
//                }
//            }
//            if( keyCycle == 0 )
//                return RESTRetUtils.errorObj(IErrorEnumImplOuter.E_5002);
//
//            // 优化各路口方案
//            int phaseno = 0;
//            int lastIntsWidth = 0;
//            for (RouteIntsection device : deviceList) {
//                Pattern pattern = device.getFeature().getPatternList().get(0);
//                // 优化各路口周期
//                cycleopt(keyCycle, device.getFeature());
//                // 保存各路口周期
//                intscycle[device.getSortid() - 1] = device.getFeature().getPatternList().get(0).getCycle();
//                // 距离默认为路口中心点之间的距离；如果设置了路口宽度，则距离应该是路口之间的路段距离
//                //得到默认距离
//                intslenth[device.getSortid() - 1] = device.getDistance();
//                // 得到上行距离
//                intslenthup[device.getSortid() - 1] = device.getDistance() + lastIntsWidth;
//                // 得到下行距离
//                intslenthdown[device.getSortid() - 1] = device.getDistance() + device.getWidth();
//
//                // 保存上一个路口的宽度，用于计算上行时下个路口的距离
//                lastIntsWidth = device.getWidth();
//
//                //得到周期
//                int cycle = device.getFeature().getPatternList().get(0).getCycle();
//                if (cycle == 0)
//                    return null;
//                //根据相位号得到协调相位值
//                if (routePara.getDirection().equals("up"))
//                    phaseno = device.getForwardphaseid();
//                else if (routePara.getDirection().equals("down"))
//                    phaseno = device.getBackphaseid();
//                else
//                    phaseno = device.getForwardphaseid();
//
//                List<List<Split>> rings = device.getFeature().getPatternList().get(0).getRings();
//
//                label:
//                for (int i = 0; i < rings.size(); i++) {
//                    List<Split> ring = rings.get(i);
//                    for (Split split : ring) {
//                        if (split.getId() == phaseno) {
//                            intssplit[device.getSortid() - 1] = split.getValue();
//                            break label;
//                        } else {
//                            intsabs[device.getSortid() - 1] += split.getValue();
//                        }
//                    }
//                }
//
//                while (intsabs[device.getSortid() - 1] >= cycle) {
//                    intsabs[device.getSortid() - 1] -= cycle;
//                }
//            }
//
//            boolean allCycleEqual = isAllCycleEqual(intscycle);
//            if (!allCycleEqual)
////                return null;
//                return RESTRetUtils.errorObj(IErrorEnumImplOuter.E_5002);
//            kdalgorithm.setAftcycle(keyCycle);
//            if (routePara.getDirection().equals("up"))
//                intsoffset = kdalgorithm.offsetOpt(routePara.getDirection(), intslenthup, intsvelup, intssplit);
//            else if (routePara.getDirection().equals("down"))
//                intsoffset = kdalgorithm.offsetOpt(routePara.getDirection(), intslenthdown, intsveldown, intssplit);
//            else
//                intsoffset = kdalgorithm.offsetByBiDirection(intslenth, intsvelup, intsveldown, intssplit);
//
//            RouteOpt routeOpt = new RouteOpt();
//            routeOpt.setDevs(routePara.getDevs());
//            List<RouteIntsection> routeOptList = routeOpt.getDevs();
//
//            for (RouteIntsection device : routeOptList) {
//
//                //把每个路口相位差转成绝对相位差，start位置也会变化
//                intsoffset[device.getSortid() - 1] -= intsabs[device.getSortid() - 1];
//                if (intsoffset[device.getSortid() - 1] < 0)
//                    intsoffset[device.getSortid() - 1] += keyCycle;
//
//                device.getFeature().getPatternList().get(0).setOffset(intsoffset[device.getSortid() - 1]);
//            }
//
//            // 计算绿波带宽
//            routeOpt.setGreenwave( getBandWidth(null,intsvelup, intsveldown, routeOptList ) );
//
//            return RESTRetUtils.successObj(routeOpt);
//        } catch (Exception e) {
//            logger.info(e.toString());
//            return RESTRetUtils.errorObj(IErrorEnumImplOuter.E_5003);
//        }
//    }
//
//    /**
//     * 获取干线协调带宽
//     * @param type 计算带宽类型，green - 绿波带宽， red - 红波带宽
//     * @param intsvelup 上行速度
//     * @param intsveldown 下行速度
//     * @param devs 路口参数
//     * @return
//     */
//    public List<Greenwave> getBandWidth(String type,double intsvelup, double intsveldown,  List<RouteIntsection> devs){
//
//        // todo: 完善红波带宽计算
//        type = "green";
//
//        int intsoffset[] = new int[devs.size()]; // 保存优化后的相位差
//        int intssplitup[] = new int[devs.size()]; // 保存路口协调相位绿信比的值
//        int intssplitdown[] = new int[devs.size()]; // 保存路口协调相位绿信比的值
//
//        int intscycle[] = new int[devs.size()]; // 保存协调路口方案的周期
////        int intsdistances[] = new int[devs.size()]; // 保存各路口的距离
//
//        // 初始化各路口协调相位绿信比
//        for (RouteIntsection dev : devs) {
//            // 保存周期
//            intscycle[dev.getSortid() - 1] = dev.getFeature().getPatternList().get(0).getCycle();
//            // 保存各路口相位差
//            intsoffset[dev.getSortid() - 1] = dev.getFeature().getPatternList().get(0).getOffset();
//            // 保存各路口距离
////            intsdistances[dev.getSortid() - 1] = dev.getDistance();
//            // 协调相位号
//            int phasenoUp;
//            phasenoUp = dev.getForwardphaseid();
//            int phasenoDown;
//            phasenoDown = dev.getBackphaseid();
//
//            List<List<Split>> rings = dev.getFeature().getPatternList().get(0).getRings();
//            // 获取参与协调相位的绿信比
//            label:
//            for (int i = 0; i < rings.size(); i++) {
//                for (Split split : rings.get(i)) {
//                    if (phasenoUp == split.getId()) {
//                        intssplitup[dev.getSortid() - 1] = split.getValue();
//                        break label;
//                    }
//                }
//            }
//            label:
//            for (int i = 0; i < rings.size(); i++) {
//                for (Split split : rings.get(i)) {
//                    if (phasenoDown == split.getId()) {
//                        intssplitdown[dev.getSortid() - 1] = split.getValue();
//                        break label;
//                    }
//                }
//            }
//        }
//
//        kdalgorithm.calbandwidth("up",intsvelup, intssplitup,intsoffset );
//        kdalgorithm.calbandwidth("down",intsveldown, intssplitdown,intsoffset );
//
//        List<Greenwave> greenwaveList = new LinkedList<>();
//        greenwaveList.add(kdalgorithm.getGwup());
//        greenwaveList.add(kdalgorithm.getGwdown());
//
//        return greenwaveList;
//    }
//
//    private void cycleopt(int keyCycle, Feature feature) {
//        Pattern pattern = feature.getPatternList().get(0);
//        List<Phase> phase = feature.getPhaseList();
//
//        CrossConfig crossConfig = new CrossConfig();
//        crossConfig.setType("cycle-opt");
//        crossConfig.setOptcycle(keyCycle);
//        crossConfig.setPattern(pattern);
//        crossConfig.setPhaseList(phase);
//
//        crossConfig.init();
//        Cross cross = Cross.builder()
//                .agentid(crossConfig.getAgentid())
//                .crossConfig(crossConfig)
//                .phaseMap(new HashMap<>())
//                .build();
//        cross.updatePhaseMap();
//
//        FixedtimePlan fixedtimePlan = cross.optimize();
//        int ringnum = 0;
//        for(Ring ring : fixedtimePlan.getRings() ){
//            int phasenum = 0;
//            for ( Integer id : ring.getSequence() ){
//                pattern.getRings().get(ringnum).get(phasenum).setValue((int) cross.getPhaseMap().get(id).getDuration());
//                phasenum++;
//            }
//            ringnum++;
//        }
//        pattern.setCycle(keyCycle);
//    }
//
//
//
//}
